#include "Nano100Series.h"
#include "I2c.h"
#include "I2c0.h"
#include "Common.h"

void I2c0Init(void)
{
	I2C_Open(I2C0, 400000);
}

int I2c0Xfer(struct i2c_msg_t *i2c_msg)
{
	int i;
	int ret = 0;

	/* start */
	I2C_SET_CONTROL_REG(I2C0, I2C_STA);
	I2C_WAIT_READY(I2C0);
	if (I2C_GET_STATUS(I2C0) != 0x08) {		// START transmitted
		ret = -1;
		goto stop;
	}

	/* addr */
	I2C_SET_DATA(I2C0, (i2c_msg->addr << 1)); 
	I2C_SET_CONTROL_REG(I2C0, I2C_SI);
	I2C_WAIT_READY(I2C0);
	if (I2C_GET_STATUS(I2C0) != 0x18) {		// SLA+W transmitted and ACK received
		ret = -1;
		goto stop;
	}

	/* write */
	for (i = 0; i < i2c_msg->tx_to_write; i++) {
		I2C_SET_DATA(I2C0, i2c_msg->tx_buf[i]);
        I2C_SET_CONTROL_REG(I2C0, I2C_SI);
		I2C_WAIT_READY(I2C0);
		if (I2C_GET_STATUS(I2C0) != 0x28) {	// DATA transmitted and ACK received
			ret = -1;
			goto stop;
		}
		i2c_msg->tx_write++;
	}

	if (i2c_msg->rx_to_read == 0) {
		ret = 0;
		goto stop;
	}

	/* restart */
	I2C_SET_CONTROL_REG(I2C0, I2C_STA | I2C_SI);
	I2C_WAIT_READY(I2C0);
	if (I2C_GET_STATUS(I2C0) != 0x10) {		// RESTART transmitted
		ret = -1;
		goto stop;
	}

	/* addr */
	I2C_SET_DATA(I2C0, ((i2c_msg->addr << 1) | 0x01)); 
	I2C_SET_CONTROL_REG(I2C0, I2C_SI);
	I2C_WAIT_READY(I2C0);
	if (I2C_GET_STATUS(I2C0) != 0x40) {		// SLA+R transmitted and ACK received
		ret = -1;
		goto stop;
	}

	/* read */
	for (i = 0; i < (i2c_msg->rx_to_read - 1); i++) {
		I2C_SET_CONTROL_REG(I2C0, I2C_AA | I2C_SI); // I2C_AA for next byte transfer
		I2C_WAIT_READY(I2C0);
		if (I2C_GET_STATUS(I2C0) != 0x50) {	// DATA transmitted and ACK received
			ret = -1;
			goto stop;
		}
		i2c_msg->rx_buf[i] = I2C_GET_DATA(I2C0);
		i2c_msg->rx_read++;
	}
	I2C_SET_CONTROL_REG(I2C0, I2C_SI); 	// fixme, I2C_NACK for next byte transfer
	I2C_WAIT_READY(I2C0);
	if (I2C_GET_STATUS(I2C0) != 0x58) {	// DATA transmitted and NACK received
		ret = -1;
		goto stop;
	}
	i2c_msg->rx_buf[i] = I2C_GET_DATA(I2C0);
	i2c_msg->rx_read++;
   
stop:
	I2C_SET_CONTROL_REG(I2C0, I2C_STO | I2C_SI);

	if (ret != 0) {
		LogDebug("I2c1Xfer error\n");
	}
	return ret;
}
